package com.pig4cloud.common.seate.properties;

import cn.hutool.core.lang.Dict;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Map;

@Data
@Accessors(chain = true)
@NoArgsConstructor
@ConfigurationProperties("spring.seate.store")
public class SeateFileProperties {


    /**
     * metrics : {"enabled":false,"exporterList":"prometheus","exporterPrometheusPort":9898,"registryType":"compact"}
     * server : {"maxCommitRetryTimeout":"-1","maxRollbackRetryTimeout":"-1","recovery":{"asynCommittingRetryPeriod":1000,"committingRetryPeriod":1000,"rollbackingRetryPeriod":1000,"timeoutRetryPeriod":1000},"rollbackRetryTimeoutUnlockEnable":false,"undo":{"logDeletePeriod":86400000,"logSaveDays":7}}
     * store : {"db":{"branchTable":"branch_table","datasource":"druid","dbType":"mysql","driverClassName":"com.mysql.jdbc.Driver","globalTable":"global_table","lockTable":"lock_table","maxConn":30,"minConn":5,"password":"mysql","queryLimit":100,"url":"jdbc:mysql://127.0.0.1:3306/seata","user":"mysql"},"file":{"dir":"sessionStore","fileWriteBufferCacheSize":16384,"flushDiskMode":"async","maxBranchSessionSize":16384,"maxGlobalSessionSize":512,"sessionReloadReadSize":100},"mode":"file"}
     * transport : {"compressor":"none","enableClientBatchSendRequest":false,"heartbeat":true,"serialization":"seata","server":"NIO","shutdown":{"wait":3},"threadFactory":{"bossThreadPrefix":"NettyBoss","bossThreadSize":1,"clientSelectorThreadPrefix":"NettyClientSelector","clientSelectorThreadSize":1,"clientWorkerThreadPrefix":"NettyClientWorkerThread","serverExecutorThreadPrefix":"NettyServerBizHandler","shareBossWorker":false,"workerThreadPrefix":"NettyServerNIOWorker","workerThreadSize":"default"},"type":"TCP"}
     */

    private MetricsProperties metrics = new MetricsProperties();
    private ServerProperties server = new ServerProperties();
    private StoreProperties store = new StoreProperties();
    private TransportProperties transport = new TransportProperties();
    private StoreFile file= new StoreFile();
    private StoreDb db = new StoreDb();

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    public static class StoreFile {
        private String dir = "sessionStore";
        private long maxBranchSessionSize = 16384;
        private long maxGlobalSessionSize = 512;
        private long fileWriteBufferCacheSize = 16384;
        private long sessionReloadReadSize = 100;
        private String flushDiskMode = "async";
    }

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    public static class StoreDb {
        private String datasource = "auto";
        private String dbType = "mysql";
        private String driverClassName = "com.mysql.jdbc.Driver";
        private String url = "jdbc:mysql://127.0.0.1:3306/seata";
        private String user = "mysql";
        private String password = "mysql";
        private long minConn = 5;
        private long maxConn = 30;
        private String globalTable = "global_table";
        private String branchTable = "branch_table";
        private String lockTable = "lock_table";
        private long queryLimit = 100;
        private long maxWait = 5000;
    }

    @NoArgsConstructor
    @Data
    public static class MetricsProperties {
        /**
         * enabled : false
         * exporterList : prometheus
         * exporterPrometheusPort : 9898
         * registryType : compact
         */

        private boolean enabled;
        private String exporterList = "prometheus";
        private int exporterPrometheusPort = 9898;
        private String registryType = "compact";
    }

    @NoArgsConstructor
    @Data
    public static class ServerProperties {
        /**
         * maxCommitRetryTimeout : -1
         * maxRollbackRetryTimeout : -1
         * recovery : {"asynCommittingRetryPeriod":1000,"committingRetryPeriod":1000,"rollbackingRetryPeriod":1000,"timeoutRetryPeriod":1000}
         * rollbackRetryTimeoutUnlockEnable : false
         * undo : {"logDeletePeriod":86400000,"logSaveDays":7}
         */

        private long maxCommitRetryTimeout = -1;
        private long maxRollbackRetryTimeout = -1;
        private RecoveryProperties recovery = new RecoveryProperties();
        private boolean rollbackRetryTimeoutUnlockEnable;
        private UndoProperties undo = new UndoProperties();
        private boolean disableGlobalTransaction;
        private boolean enableDegrade;
        private Map<String, Object> vgroupMapping = Dict.create().set("my_test_tx_group","default");
        private Map<String, Object> defaults = Dict.create().set("grouplist","127.0.0.1:8770");

        @NoArgsConstructor
        @Data
        public static class RecoveryProperties {
            /**
             * asynCommittingRetryPeriod : 1000
             * committingRetryPeriod : 1000
             * rollbackingRetryPeriod : 1000
             * timeoutRetryPeriod : 1000
             */

            private int asynCommittingRetryPeriod = 1000;
            private int committingRetryPeriod = 1000;
            private int rollbackingRetryPeriod = 1000;
            private int timeoutRetryPeriod = 1000;
        }

        @NoArgsConstructor
        @Data
        public static class UndoProperties {
            /**
             * logDeletePeriod : 86400000
             * logSaveDays : 7
             */

            private int logDeletePeriod = 86400000;
            private int logSaveDays = 7;
        }
    }

    @NoArgsConstructor
    @Data
    public static class StoreProperties {
        /**
         * db : {"branchTable":"branch_table","datasource":"druid","dbType":"mysql","driverClassName":"com.mysql.jdbc.Driver","globalTable":"global_table","lockTable":"lock_table","maxConn":30,"minConn":5,"password":"mysql","queryLimit":100,"url":"jdbc:mysql://127.0.0.1:3306/seata","user":"mysql"}
         * file : {"dir":"sessionStore","fileWriteBufferCacheSize":16384,"flushDiskMode":"async","maxBranchSessionSize":16384,"maxGlobalSessionSize":512,"sessionReloadReadSize":100}
         * mode : file
         */

        private DbProperties db = new DbProperties();
        private FileProperties file = new FileProperties();
        private String mode = "db";

        @NoArgsConstructor
        @Data
        public static class DbProperties {
            /**
             * branchTable : branch_table
             * datasource : druid
             * dbType : mysql
             * driverClassName : com.mysql.jdbc.Driver
             * globalTable : global_table
             * lockTable : lock_table
             * maxConn : 30
             * minConn : 5
             * password : mysql
             * queryLimit : 100
             * url : jdbc:mysql://127.0.0.1:3306/seata
             * user : mysql
             */

            private String branchTable = "branch_table";
            private String datasource = "auto";
            private String dbType = "mysql";
            private String driverClassName;
            private String globalTable = "global_table";
            private String lockTable = "lock_table";
            private int maxConn;
            private int minConn;
            private String password;
            private int queryLimit;
            private String url;
            private String user;
        }

        @NoArgsConstructor
        @Data
        public static class FileProperties {
            /**
             * dir : sessionStore
             * fileWriteBufferCacheSize : 16384
             * flushDiskMode : async
             * maxBranchSessionSize : 16384
             * maxGlobalSessionSize : 512
             * sessionReloadReadSize : 100
             */

            private String dir = "sessionStore";
            private int fileWriteBufferCacheSize = 16384;
            private String flushDiskMode = "async";
            private int maxBranchSessionSize = 16384;
            private int maxGlobalSessionSize = 512;
            private int sessionReloadReadSize = 100;
        }
    }

    @NoArgsConstructor
    @Data
    public static class TransportProperties {
        /**
         * compressor : none
         * enableClientBatchSendRequest : false
         * heartbeat : true
         * serialization : seata
         * server : NIO
         * shutdown : {"wait":3}
         * threadFactory : {"bossThreadPrefix":"NettyBoss","bossThreadSize":1,"clientSelectorThreadPrefix":"NettyClientSelector","clientSelectorThreadSize":1,"clientWorkerThreadPrefix":"NettyClientWorkerThread","serverExecutorThreadPrefix":"NettyServerBizHandler","shareBossWorker":false,"workerThreadPrefix":"NettyServerNIOWorker","workerThreadSize":"default"}
         * type : TCP
         */

        private String compressor = "none";
        private boolean enableClientBatchSendRequest;
        private boolean heartbeat = true;
        private String serialization = "seata";
        private String server = "NIO";
        private ShutdownProperties shutdown = new ShutdownProperties();
        private ThreadFactoryProperties threadFactory = new ThreadFactoryProperties();
        private String type = "TCP";

        @NoArgsConstructor
        @Data
        public static class ShutdownProperties {
            /**
             * wait : 3
             */

            private int wait = 3;
        }

        @NoArgsConstructor
        @Data
        public static class ThreadFactoryProperties {
            /**
             * bossThreadPrefix : NettyBoss
             * bossThreadSize : 1
             * clientSelectorThreadPrefix : NettyClientSelector
             * clientSelectorThreadSize : 1
             * clientWorkerThreadPrefix : NettyClientWorkerThread
             * serverExecutorThreadPrefix : NettyServerBizHandler
             * shareBossWorker : false
             * workerThreadPrefix : NettyServerNIOWorker
             * workerThreadSize : default
             */

            private String bossThreadPrefix = "NettyBoss";
            private int bossThreadSize = 1;
            private String clientSelectorThreadPrefix = "NettyClientSelector";
            private int clientSelectorThreadSize = 1;
            private String clientWorkerThreadPrefix = "NettyClientWorkerThread";
            private String serverExecutorThreadPrefix = "NettyServerBizHandler";
            private boolean shareBossWorker;
            private String workerThreadPrefix = "NettyServerNIOWorker";
            private String workerThreadSize = "default";
        }
    }
}
